#include "Regulation.h"
#include <string>
/************************************************************
*类名：Regulation
*功能：中缀表达式合法性的判断
*作者：韦锴祖
*日期：2018年12月10号
************************************************************/

/**
* 功能：对输入的中缀表达式进行合法性的判断
* 参数：dot 小数点的个数
*      leftBracket 左括号个数
*      rightBracket 右括号个数
* 作者：韦锴祖
* 日期：2018-12-8
*/

bool Regulation::IsEndswith(const string& str, const string& end)
{
	int srclen = str.size();
	int endlen = end.size();
	if (srclen >= endlen)
	{
		string temp = str.substr(srclen - endlen, endlen);
		if (temp == end)
			return true;
	}

	return false;
}

bool Regulation::IsRegulation(const string& str)
{
	int dot = 0;                          /**< 定义并初始化小数点的个数 */
	int leftBracket = 0;                  /**< 定义并初始化左括号个数 */
	int rightBracket = 0;                 /**< 定义并初始化右括号个数 */

										  /**< 判断输入的字符串末尾是否有+ - * /号，有则报错 */
	if (IsEndswith(str,"+") || IsEndswith(str, "-") || IsEndswith(str, "*") || IsEndswith(str, "/")
		|| IsEndswith(str, ".") || IsEndswith(str, "%") || IsEndswith(str, "^"))
	{
		cout << "This expression is error." << endl;
		return false;
	}
	else
	{
		if (str.at(0) == '(')
		{
			leftBracket++;
		}
	}

	for (unsigned int i = 1; i < str.length(); i++)  /**< 遍历整个QString */
	{
		switch (str.at(i))
		{
			/**< 当前字符为"("时，上一字符不能是小数点、右括号、数字 */
		case '(':
			dot = 0;
			if (str.at(i - 1) == '.' || str.at(i - 1) == ')' || (str.at(i - 1) <= '9' && str.at(i - 1) >= '0'))
			{
				cout << "This expression is error."<<endl;
				return false;
			}
			leftBracket++;
			break;

			/**< 当前字符为)时，上一字符必须是数字、右括号或者阶乘 */
		case ')':
			dot = 0;
			if (leftBracket == 0)
			{
				cout << "This expression is error." << endl;
				return false;
			}		
			else if (!((str.at(i - 1) <= '9' && str.at(i - 1) >= '0') || str.at(i - 1) == ')' || str.at(i - 1) == '!'))
			{
				cout << "This expression is error." << endl;
				return false;
			}
			rightBracket++;
			break;

			/**< 当前字符为加减乘除时，上一字符只能为数字、右括号或者阶乘 */
		case '+':
		case '*':
		case '^':
			dot = 0;
			if (!((str.at(i - 1) <= '9' && str.at(i - 1) >= '0') || str.at(i - 1) == ')' || str.at(i - 1) == '!'))
			{
				cout << "This expression is error." << endl;
				return false;
			}
			break;

		case '/':
			dot = 0;
			if (!((str.at(i - 1) <= '9' && str.at(i - 1) >= '0') || str.at(i - 1) == ')' || str.at(i - 1) == '!'))
			{
				cout << "This expression is error." << endl;
				return false;
			}
			else if (str.at(i + 1) != 0 && str.at(i + 1) == '0')
			{
				cout << "This expression is error." << endl;
				return false;
			}
			break;

		case '%':
			dot = 0;
			if (!((str.at(i - 1) <= '9' && str.at(i - 1) >= '0') || str.at(i - 1) == ')' || str.at(i - 1) == '!'))
			{
				cout << "This expression is error." << endl;
				return false;
			}
			else if (str.at(i + 1) != 0 && str.at(i + 1) == '0')
			{
				cout << "This expression is error." << endl;
				return false;
			}
			break;

			/**< 当前字符为-时，上一字符只能为数字、括号或者阶乘 */
		case '-':
			dot = 0;
			if (!((str.at(i - 1) <= '9' && str.at(i - 1) >= '0') || str.at(i - 1) == ')' || str.at(i - 1) == '!' || str.at(i - 1) == '('))
			{
				cout << "This expression is error." << endl;
				return false;
			}
			break;

			/**< 当前字符为阶乘时，上一字符必须为数字或者右括号 */
		case '!':
			dot = 0;
#if 0
			if (str.at(i + 1) != NULL && str.at(i + 1) <= '9' && str.at(i+1) >= '0')
			{
				cout << "This expression is error." << endl;
				return false;
			}
#endif
			if (!((str.at(i - 1) <= '9' && str.at(i - 1) >= '0') || str.at(i - 1) == ')'))
			{
				cout << "This expression is error." << endl;
				return false;
			}
			break;

			/**< 当前字符为小数点时，上一字符必须为数字 */
		case '.':
			dot++;
			if (!(str.at(i - 1) <= '9' && str.at(i - 1) >= '0'))
			{
				cout << "This expression is error." << endl;
				return false;
			}
			else if (dot > 1)
			{
				cout << "This expression is error." << endl;
				return false;
			}
			break;

		default:
			if (str.at(i - 1) == ')')
			{
				cout << "This expression is error." << endl;
				return false;
			}
			break;
		}

	}

	/**< 左右括号数目不相等 */
	if (leftBracket != rightBracket)
	{
		cout << "This expression is error." << endl;
		return false;
	}
	return true;
}




